from rest_framework import serializers
from django.contrib.auth import authenticate
from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import Permission
import secrets
import string
from .models import User
from apps.permissions.models import PermissionExtension


class UserSerializer(serializers.ModelSerializer):
    """用户基础序列化器"""
    
    class Meta:
        model = User
        fields = '__all__'
        read_only_fields = ['id', 'created_at', 'updated_at', 'last_login_at', 'is_staff', 'is_superuser']
        extra_kwargs = {
            'password': {'write_only': True},
        }


class UserRegistrationSerializer(serializers.ModelSerializer):
    """用户注册序列化器"""
    password = serializers.CharField(write_only=True, help_text="密码")
    password_confirm = serializers.CharField(write_only=True, help_text="确认密码")
    
    class Meta:
        model = User
        fields = ['username', 'email', 'password', 'password_confirm', 'real_name', 'phone']
        extra_kwargs = {
            'username': {'help_text': '用户名'},
            'email': {'help_text': '邮箱地址'},
            'real_name': {'help_text': '真实姓名', 'required': False},
            'phone': {'help_text': '手机号', 'required': False},
        }
    
    def validate_email(self, value):
        """验证邮箱唯一性"""
        if User.objects.filter(email=value).exists():
            raise serializers.ValidationError("该邮箱已被注册")
        return value
    
    def validate_username(self, value):
        """验证用户名唯一性"""
        if User.objects.filter(username=value).exists():
            raise serializers.ValidationError("该用户名已被注册")
        return value
    
    def validate(self, attrs):
        """验证密码一致性"""
        password = attrs.get('password')
        password_confirm = attrs.pop('password_confirm', None)
        
        if password != password_confirm:
            raise serializers.ValidationError({"password_confirm": "两次输入的密码不一致"})
        
        # 验证密码强度
        try:
            validate_password(password)
        except ValidationError as e:
            raise serializers.ValidationError({"password": e.messages})
        
        return attrs
    
    def create(self, validated_data):
        """创建用户"""
        password = validated_data.pop('password')
        user = User.objects.create_user(**validated_data)
        user.set_password(password)
        user.save()
        return user


class UserLoginSerializer(serializers.Serializer):
    """用户登录序列化器"""
    username = serializers.CharField(help_text="用户名或邮箱")
    password = serializers.CharField(write_only=True, help_text="密码")
    
    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        
        if username and password:
            # 支持用户名或邮箱登录
            user = None
            if '@' in username:
                # 邮箱登录
                try:
                    user_obj = User.objects.get(email=username)
                    user = authenticate(username=user_obj.username, password=password)
                except User.DoesNotExist:
                    pass
            else:
                # 用户名登录
                user = authenticate(username=username, password=password)
            
            if not user:
                raise serializers.ValidationError("用户名或密码错误")
            
            if not user.can_login():
                raise serializers.ValidationError("账户已被禁用或未激活")
            
            attrs['user'] = user
        else:
            raise serializers.ValidationError("必须提供用户名和密码")
        
        return attrs


class UserProfileSerializer(serializers.ModelSerializer):
    """用户个人信息序列化器"""

    class Meta:
        model = User
        fields = '__all__'
        read_only_fields = [
            'id', 'username', 'password', 'last_login', 'date_joined',
            'created_at', 'updated_at', 'last_login_at',
            'is_staff', 'is_superuser', 'is_active',  # 权限字段只读，防止用户自己修改权限
            'groups', 'user_permissions'  # 权限组字段只读
        ]


class UserPasswordChangeSerializer(serializers.Serializer):
    """用户密码修改序列化器"""
    old_password = serializers.CharField(write_only=True, help_text="原密码")
    new_password = serializers.CharField(write_only=True, help_text="新密码")
    new_password_confirm = serializers.CharField(write_only=True, help_text="确认新密码")
    
    def validate_old_password(self, value):
        """验证原密码"""
        user = self.context['request'].user
        if not user.check_password(value):
            raise serializers.ValidationError("原密码错误")
        return value
    
    def validate(self, attrs):
        """验证新密码一致性"""
        new_password = attrs.get('new_password')
        new_password_confirm = attrs.get('new_password_confirm')
        
        if new_password != new_password_confirm:
            raise serializers.ValidationError({"new_password_confirm": "两次输入的新密码不一致"})
        
        # 验证密码强度
        try:
            validate_password(new_password)
        except ValidationError as e:
            raise serializers.ValidationError({"new_password": e.messages})
        
        return attrs
    
    def save(self):
        """保存新密码"""
        user = self.context['request'].user
        user.set_password(self.validated_data['new_password'])
        user.save()
        return user


class UserTokenSerializer(serializers.Serializer):
    """用户Token响应序列化器"""
    access = serializers.CharField(help_text="访问令牌")
    refresh = serializers.CharField(help_text="刷新令牌")
    user = UserProfileSerializer(help_text="用户信息")


class TokenObtainPairSerializer(serializers.Serializer):
    """Token获取序列化器 - 兼容JWT标准格式"""
    email = serializers.EmailField(help_text="邮箱地址")
    password = serializers.CharField(write_only=True, help_text="密码")

    def validate(self, attrs):
        email = attrs.get('email')
        password = attrs.get('password')

        if email and password:
            # 邮箱登录 - 直接验证密码
            try:
                user = User.objects.get(email=email)
                if not user.check_password(password):
                    raise serializers.ValidationError("邮箱或密码错误")
            except User.DoesNotExist:
                raise serializers.ValidationError("邮箱或密码错误")

            if not user.can_login():
                raise serializers.ValidationError("账户已被禁用或未激活")

            attrs['user'] = user
        else:
            raise serializers.ValidationError("必须提供邮箱和密码")

        return attrs


class UserPasswordResetSerializer(serializers.Serializer):
    """管理员重置用户密码序列化器"""
    new_password = serializers.CharField(
        required=False,
        write_only=True,
        help_text="新密码（可选，不提供则自动生成）"
    )
    auto_generate = serializers.BooleanField(
        default=True,
        help_text="是否自动生成密码"
    )

    def validate_new_password(self, value):
        """验证新密码"""
        if value:
            try:
                validate_password(value)
            except ValidationError as e:
                raise serializers.ValidationError(list(e.messages))
        return value

    def generate_random_password(self, length=12):
        """生成随机密码"""
        # 包含大小写字母、数字和特殊字符
        characters = string.ascii_letters + string.digits + "!@#$%^&*"
        password = ''.join(secrets.choice(characters) for _ in range(length))

        # 确保密码包含至少一个大写字母、小写字母、数字和特殊字符
        if (any(c.islower() for c in password) and
            any(c.isupper() for c in password) and
            any(c.isdigit() for c in password) and
            any(c in "!@#$%^&*" for c in password)):
            return password
        else:
            # 如果不满足条件，递归重新生成
            return self.generate_random_password(length)

    def save(self, user):
        """重置用户密码"""
        auto_generate = self.validated_data.get('auto_generate', True)
        new_password = self.validated_data.get('new_password')

        if auto_generate or not new_password:
            # 自动生成密码
            new_password = self.generate_random_password()

        # 设置新密码
        user.set_password(new_password)
        user.save(update_fields=['password'])

        return {
            'user': user,
            'new_password': new_password,
            'auto_generated': auto_generate or not self.validated_data.get('new_password')
        }


# ==================== 用户权限管理序列化器 ====================

class UserPermissionExtensionSerializer(serializers.ModelSerializer):
    """用户权限扩展序列化器 - 用于权限分配"""
    category_name = serializers.CharField(source='category.name', read_only=True)

    # 权限相关字段
    permission_id = serializers.IntegerField(source='permission.id', read_only=True)
    permission_codename = serializers.CharField(source='permission.codename', read_only=True)
    permission_name = serializers.CharField(source='permission.name', read_only=True)
    permission_app_label = serializers.CharField(source='permission.content_type.app_label', read_only=True)
    permission_model = serializers.CharField(source='permission.content_type.model', read_only=True)

    class Meta:
        model = PermissionExtension
        fields = [
            'id', 'category_name', 'module', 'description', 'api_endpoint', 'status',
            'permission_id', 'permission_codename', 'permission_name',
            'permission_app_label', 'permission_model'
        ]
        read_only_fields = [
            'id', 'category_name', 'module', 'description', 'api_endpoint', 'status',
            'permission_id', 'permission_codename', 'permission_name',
            'permission_app_label', 'permission_model'
        ]


class UserSetPermissionsSerializer(serializers.Serializer):
    """设置用户权限序列化器"""
    permission_extension_ids = serializers.ListField(
        child=serializers.IntegerField(),
        help_text="权限扩展ID列表",
        allow_empty=True
    )

    def validate_permission_extension_ids(self, value):
        """验证权限扩展ID"""
        if not isinstance(value, list):
            raise serializers.ValidationError("permission_extension_ids必须是数组")

        # 验证权限扩展是否存在
        existing_extensions = PermissionExtension.objects.filter(id__in=value, status='active')
        if len(existing_extensions) != len(value):
            invalid_ids = set(value) - set(existing_extensions.values_list('id', flat=True))
            raise serializers.ValidationError(f"权限扩展ID无效: {list(invalid_ids)}")

        return value


class UserPermissionOperationResultSerializer(serializers.Serializer):
    """用户权限操作结果序列化器"""
    count = serializers.IntegerField(help_text="操作的权限数量")
    message = serializers.CharField(help_text="操作结果消息")
